/* Copyright 2009
 *
 * This program and the accompanying materials
 * are made available under the terms of the
 * Eclipse Public License v1.0 which accompanies
 * this distribution, and is available at
 *
 * 		http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
 * OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * Contributors:
 * 	   IBM Corporation - initial API and implementation for JDT/DLTK
 *     Sean W. Quinn - initial adoption for use with PHP from various sources.
 */
package org.eclipse.php.core;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.core.IOpenable;
import org.eclipse.dltk.core.IParent;
import org.eclipse.dltk.core.ISourceManipulation;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.WorkingCopyOwner;
import org.eclipse.php.internal.core.PHPCorePluginExt;

/**
 * A package fragment is a portion of the workspace corresponding to an entire
 * package, or to a portion thereof. The distinction between a package fragment
 * and a package is that a package with some name is the union of all package
 * fragments in the class path which have the same name.
 * <p>
 * Package fragments elements need to be opened before they can be navigated or
 * manipulated. The children are of type <code>IProgramUnit</code> (representing
 * a source file) or <code>IScriptFile</code> (representing a binary class
 * file). The children are listed in no particular order.
 * </p>
 *
 * @noimplement This interface is not intended to be implemented by clients.
 */
public interface INamespaceFragment extends IParent, IPHPElement, IOpenable, ISourceManipulation {

	/**
	 * <p>
	 * The name of package fragment for the default package (value: the empty
	 * string, <code>""</code>).
	 * </p>
	 */
	public static final String DEFAULT_PACKAGE_NAME = ""; //$NON-NLS-1$

	/**
	 * Returns whether this fragment contains at least one Java resource.
	 *
	 * @return true if this fragment contains at least one Java resource, false
	 *         otherwise
	 * @exception PHPModelException if this element does not exist or if an
	 *                exception occurs while accessing its corresponding
	 *                resource.
	 * @throws ModelException
	 */
	boolean containsPHPResources() throws ModelException;

	/**
	 * Creates and returns a compilation unit in this package fragment with the
	 * specified name and contents. No verification is performed on the
	 * contents.
	 * <p>
	 * It is possible that a compilation unit with the same name already exists
	 * in this package fragment. The value of the <code>force</code> parameter
	 * effects the resolution of such a conflict:
	 * <ul>
	 * <li> <code>true</code> - in this case the compilation is created with the
	 * new contents</li>
	 * <li> <code>false</code> - in this case a <code>PHPModelException</code> is
	 * thrown</li>
	 * </ul>
	 *
	 * @param contents the given contents
	 * @param force specify how to handle conflict is the same name already
	 *            exists
	 * @param monitor the given progress monitor
	 * @param name the given name
	 * @exception PHPModelException if the element could not be created. Reasons
	 *                include:
	 *                <ul>
	 *                <li> This Java element does not exist
	 *                (ELEMENT_DOES_NOT_EXIST)</li> <li> A <code>CoreException
	 *                </code> occurred while creating an underlying resource
	 *                <li> The name is not a valid compilation unit name
	 *                (INVALID_NAME) <li> The contents are <code>null</code>
	 *                (INVALID_CONTENTS)
	 *                </ul>
	 * @return a compilation unit in this package fragment with the specified
	 *         name and contents
	 */
	IProgramUnit createProgramUnit(String name, String contents, boolean force, IProgressMonitor monitor)
			throws PHPModelException;

	/**
	 * Returns the class file with the specified name in this package (for
	 * example, <code>"Object.class"</code>). The ".class" suffix is required.
	 * This is a handle-only method. The class file may or may not be present.
	 *
	 * @param name the given name
	 * @return the class file with the specified name in this package
	 */
	IScriptFile getScriptFile(String name);

	/**
	 * Returns all of the class files in this package fragment.
	 * <p>
	 * Note: it is possible that a package fragment contains only compilation
	 * units (in other words, its kind is <code>K_SOURCE</code>), in which case
	 * this method returns an empty collection.
	 *
	 * @exception PHPModelException if this element does not exist or if an
	 *                exception occurs while accessing its corresponding
	 *                resource.
	 * @return all of the class files in this package fragment
	 */
	IScriptFile[] getScriptFiles() throws PHPModelException;

	/**
	 * Returns the compilation unit with the specified name in this package (for
	 * example, <code>"Object.java"</code>). The name has to be a valid
	 * compilation unit name. This is a handle-only method. The compilation unit
	 * may or may not be present.
	 *
	 * @param name the given name
	 * @return the compilation unit with the specified name in this package
	 * @see PHPConventions#validateProgramUnitName(String name, String
	 *      sourceLevel, String complianceLevel)
	 */
	IProgramUnit getProgramUnit(String name);

	/**
	 * Returns all of the compilation units in this package fragment.
	 * <p>
	 * Note: it is possible that a package fragment contains only class files
	 * (in other words, its kind is <code>K_BINARY</code>), in which case this
	 * method returns an empty collection.
	 * </p>
	 *
	 * @exception PHPModelException if this element does not exist or if an
	 *                exception occurs while accessing its corresponding
	 *                resource.
	 * @return all of the compilation units in this package fragment
	 */
	IProgramUnit[] getProgramUnits() throws PHPModelException;

	/**
	 * Returns all of the compilation units in this package fragment that are in
	 * working copy mode and that have the given owner.
	 * <p>
	 * Only existing working copies are returned. So a compilation unit handle
	 * that has no corresponding resource on disk will be included if and only
	 * if is in working copy mode.
	 * </p>
	 * <p>
	 * Note: it is possible that a package fragment contains only class files
	 * (in other words, its kind is <code>K_BINARY</code>), in which case this
	 * method returns an empty collection.
	 * </p>
	 *
	 * @param owner the owner of the returned compilation units
	 * @exception PHPModelException if this element does not exist or if an
	 *                exception occurs while accessing its corresponding
	 *                resource.
	 * @return all of the compilation units in this package fragment
	 * @since 3.0
	 */
	IProgramUnit[] getProgramUnits(WorkingCopyOwner owner) throws PHPModelException;

	/**
	 * Returns the dot-separated package name of this fragment, for example
	 * <code>"java.lang"</code>, or <code>""</code> (the empty string), for the
	 * default package.
	 *
	 * @return the dot-separated package name of this fragment
	 */
	String getElementName();

	/**
	 * Returns this package fragment's root kind encoded as an integer. A
	 * package fragment can contain source files (i.e. files with one of the
	 * {@link PHPCorePluginExt#getPHPLikeExtensions() Java-like extensions}), or
	 * <code>.class</code> files. This is a convenience method.
	 *
	 * @exception PHPModelException if this element does not exist or if an
	 *                exception occurs while accessing its corresponding
	 *                resource.
	 * @return this package fragment's root kind encoded as an integer
	 * @throws ModelException
	 * @see INamespaceFragmentRoot#K_SOURCE
	 * @see INamespaceFragmentRoot#K_BINARY
	 */
	int getKind() throws ModelException;

	/**
	 * Returns an array of non-Java resources contained in this package
	 * fragment.
	 * <p>
	 * Non-Java resources includes other files and folders located in the same
	 * directory as the compilation units or class files for this package
	 * fragment. Source files excluded from this package by virtue of
	 * inclusion/exclusion patterns on the corresponding source classpath entry
	 * are considered non-Java resources and will appear in the result (possibly
	 * in a folder).
	 * </p>
	 * <p>
	 * Since 3.3, if this package fragment is inside an archive, the non-Java
	 * resources are a tree of {@link IPharEntryResource}s. One can navigate
	 * this tree using the {@link IPharEntryResource#getChildren()} and
	 * {@link IPharEntryResource#getParent()} methods.
	 * </p>
	 *
	 * @exception PHPModelException if this element does not exist or if an
	 *                exception occurs while accessing its corresponding
	 *                resource.
	 * @return an array of non-Java resources (<code>IFile</code>s,
	 *         <code>IFolder</code>s, or <code>IStorage</code>s if the package
	 *         fragment is in an archive) contained in this package fragment
	 * @throws ModelException
	 * @see IBuildpathEntry#getInclusionPatterns()
	 * @see IBuildpathEntry#getExclusionPatterns()
	 */
	Object[] getNonPHPResources() throws ModelException;

	/**
	 * Returns whether this package fragment's name is a prefix of other package
	 * fragments in this package fragment's root.
	 *
	 * @exception PHPModelException if this element does not exist or if an
	 *                exception occurs while accessing its corresponding
	 *                resource.
	 * @return true if this package fragment's name is a prefix of other package
	 *         fragments in this package fragment's root, false otherwise
	 */
	boolean hasSubnamespaces() throws ModelException;

	/**
	 * Returns whether this package fragment is a default package. This is a
	 * handle-only method.
	 *
	 * @return true if this package fragment is a default package
	 */
	boolean isDefaultNamespace();
}
